<?php

namespace app\models;

use Yii;
use yii\db\ActiveRecord;
use yii\db\Expression;

/**
 * 卡账单
 * Class CardBill
 * @package app\models
 *
 * @property integer $id PK
 * @property integer $user_id 用户编号
 * @property integer $card_id 卡编号
 * @property integer $package_id 套餐编号
 * @property string $month 月份Ym
 * @property float $data 流量（B）
 * @property integer $sms 短信（数量）
 * @property integer $voice 语音（分钟）
 * @property float $input_octets_month 上行流量（B）
 * @property float $output_octets_month 下行流量（B）
 * @property float $cost_money 成本（上游账单金额）
 * @property float $money 金额
 * @property integer $create_time 创建时间
 *
 * @property User $user 关联用户
 * @property Card $card 关联卡
 * @property Package $package 关联套餐
 */
class CardBill extends ActiveRecord
{
    /**
     * 关联用户
     * @return \yii\db\ActiveQuery
     */
    public function getUser()
    {
        return $this->hasOne(User::class, ['id' => 'user_id']);
    }

    /**
     * 关联卡
     * @return \yii\db\ActiveQuery
     */
    public function getCard()
    {
        return $this->hasOne(Card::class, ['id' => 'card_id']);
    }

    /**
     * 关联套餐
     * @return \yii\db\ActiveQuery
     */
    public function getPackage()
    {
        return $this->hasOne(Package::class, ['id' => 'package_id']);
    }

    /**
     * 生成账单
     * 从CardUsage中读取所有指定月份的
     * @param string $month 月份201801
     * @return array|string
     */
    public static function taskGenerateBill($month)
    {
        if (CardBill::find()->andWhere(['month' => $month])->exists()) {
            return '账单已经存在【month=' . $month . '】，不能重复生成。';
        }
        /** @var CardUsage $usage */
        foreach (CardUsage::find()
            ->andWhere(['month' => preg_replace('/^(\d{4})(\d{2})$/', '$1-$2', $month)])
            ->each() as $usage) {
            $card = $usage->card;
            if (empty($card->uid)) {
                Yii::warning('生成卡【id=' . $card->id . '】【ICCID=' . $card->iccid . '】【month=' . $month . '】账单时找不到用户。');
                continue;
            }
            $bill = new CardBill();
            $bill->user_id = $card->uid;
            $bill->card_id = $card->id;
            $bill->package_id = $card->package_id;
            $bill->month = $month;
            $bill->data = $usage->data;
            $bill->sms = $usage->sms;
            $bill->voice = $usage->voice;
            $bill->input_octets_month = $usage->input_octets_month;
            $bill->output_octets_month = $usage->output_octets_month;
            $bill->cost_money = $usage->sum_price;
            $bill->create_time = time();
            $bill->money = $bill->calcMoney();
            $bill->save();
        }
        foreach (CardBill::find()
            ->andWhere(['month' => $month])
            ->asArray()
            ->select([
                'user_id' => 'user_id',
                'package_id' => 'package_id',
                'amount' => new Expression('count(0)'),
                'money' => new Expression('sum(money)'),
            ])
            ->groupBy('user_id, package_id')
            ->all() as $item) {
            $userBill = UserBill::findOne(['month' => $month, 'uid' => $item['user_id'], 'package_id' => $item['package_id']]);
            if (empty($userBill)) {
                $userBill = new UserBill();
                $userBill->uid = $item['user_id'];
                $userBill->month = $month;
                $userBill->package_id = $item['package_id'];
                $userPackage = UserPackage::findOne(['uid' => $item['user_id'], 'package_id' => $item['package_id']]);
                if (!empty($userPackage)) {
                    $userBill->price = $userPackage->cost_price;
                    $userBill->money = $item['amount'] * $userPackage->cost_price;
                } else {
                    $user = User::findOne(['id' => $item['user_id']]);
                    if (!empty($user->agent_id)) {
                        $agentPackage = AgentPackage::findOne(['agent_id' => $user->agent_id, 'package_id' => $item['package_id']]);
                        if (!empty($agentPackage)) {
                            $userBill->price = $agentPackage->sale_price;
                            $userBill->money = $item['amount'] * $agentPackage->sale_price;
                        }
                    }
                }
            }
            $userBill->card_amount = $item['amount'];
            //$userBill->money = $item['money'];
            $userBill->status = UserBill::STATUS_WAIT_CONFIRM;
            $userBill->save();
        }

        return [
            '_del' => true, // 一次性任务，执行完毕后删除
        ];
    }

    /**
     * 计算金额
     * @return float|int
     */
    private function calcMoney()
    {
        if (empty($this->package_id)) {
            return 0; // 没有设置任何套餐
        }
        $package = $this->package;
        $money = $package->price;
        /* 这里没有考虑流量池的情况，所以暂时注释掉，超过流量池的金额由人工统计报表计算
        // 计算超出流量的金额
        if (Util::comp($this->data, $package->data, 4) > 0 && !empty($package->extra_data)) {
            $extraData = $this->data - $package->data;
            $money += $extraData * $package->extra_data_price / $package->extra_data;
        }
        if ($this->sms > $package->sms && !empty($package->extra_sms_price)) {
            $money += ($this->sms - $package->sms) * $package->extra_sms_price;
        }

        if (ceil($this->voice) > $package->voice && !empty($package->extra_voice_price)) {
            $extraVoice = ceil($this->voice) - $package->voice;
            $money += $extraVoice * $package->extra_voice_price;
        }
        */

        return $money;
    }
}
